<?php


namespace frontend\modules\wechat\controllers;


use common\models\sys\SysSetting;
use common\models\wechat\WechatAccounts;
use common\models\wechat\WechatPaySetting;
use common\models\wechat\WechatReplyKeyword;
use common\models\wechat\WechatReplyRule;
use frontend\controllers\BaseController;
use yii;
use yii\web\NotFoundHttpException;
class ApiController extends BaseController
{


    public $enableCsrfValidation = false;

    public $message;
    private $_wechat;




    public function actionIndex()
    {
        // TODO 群发事件推送群发处理
        // TODO 模板消息事件推送处理
        // TODO 用户上报地理位置事件推送处理
        // TODO 自定义菜单事件推送处理
        // TODO 微信小店订单付款通知处理
        // TODO 微信卡卷(卡券通过审核、卡券被用户领取、卡券被用户删除)通知处理
        // TODO 智能设备接口
        // TODO 多客服转发处理
        $request = Yii::$app->request;

        if ($request->get('id') !== null) {          //手动绑定接管
            $id = $request->get('id');
            $wechat = $this->findWechat($id);
        }
        switch ($request->getMethod()) {
            case 'GET':
                if ($wechat->status == WechatAccounts::STATUS_INACTIVE) { // 激活公众号
                    $wechat->updateAttributes(['status' => WechatAccounts::STATUS_ACTIVE]);
                }
                return $request->getQueryParam('echostr');
            case 'POST':
                $this->setWechat($wechat);
                $this->message = \Yii::$app->wechat->server->getMessage();
                $result = $this->resolveProcess(); // 处理请求
                return is_array($result) ? $this->createResponse($result) : $result;
            default:
                throw new NotFoundHttpException('The requested page does not exist.');
        }
    }



    public function resolveProcess()
    {
        $result = null;

        //存放匹配到的规则
        $ismatch = [];
        foreach ($this->match() as $model) {
            if ($model instanceof WechatReplyKeyword) {
                $processor = $model->rule->processor;
                $module = $model->rule->module;
                $route = ($module == 'system') ? '/wechat/reply/'.$processor : '/wechat/' . $model->rule->module . '/' . $model->rule->processor;
            } elseif (isset($model['route'])) {         //假使有route直接执行
                $route = $model['route'];
            } else {
                continue;
            }

            //匹配到，存放进去
            if($route){
                $ismatch[] = $route;
            }

            // 转发路由请求 参考: Yii::$app->runAction()
            $parts = Yii::$app->createController($route);
            if (is_array($parts)) {
                list($controller, $actionID) = $parts;

                // 微信请求的处理器必须继承frontend\modules\wechat\controllers
                if (!($controller instanceof ProcessController)) {
                    throw new yii\base\InvalidCallException("Wechat process controller must instance of '" . ProcessController::className() . "'");
                }
                // 传入当前公众号和微信请求内容
                $controller->message = $this->message;
                $controller->setWechat($this->getWechat());
                $oldController = Yii::$app->controller;
                $result = $controller->runAction($actionID);
                Yii::$app->controller = $oldController;
            }
            // 如果有数据则跳出循环直接输出. 否则只作为订阅类型继续循环处理
            if ($result !== null) {
                break;
            }
        }


        //判断是否有匹配的规则，没有的话默认回复
        if(count($ismatch) == 0){
            //取出默认回复的关键字
            $kwd = SysSetting::getValue('wechat_default');
            $processor = WechatReplyKeyword::find()->alias('kwd')->select('rule.processor,kwd.content')
                ->leftJoin(['rule'=>WechatReplyRule::tableName()],'kwd.rid=rule.id')
                ->where(['kwd.content'=>$kwd])
                ->asArray()
                ->one();
            //回复
            if(!empty($processor)){
                Yii::$app->runAction('/wechat/reply/'.$processor['processor'],['content'=>$processor['content']]);
            }else{      //没有匹配的，直接回复设置的话语
                $server = \Yii::$app->wechat->server;
                $server->setMessageHandler(function ($message) use($kwd) {
                    return $kwd;
                });
                $response = $server->serve();
                $response->send();
            }
        }

        return $result;
    }


    /**
     * 设置当前公众号
     * @param Wechat $wechat
     */
    public function setWechat(WechatAccounts $wechat)
    {
        $this->_wechat = $wechat;
    }

    /**
     * @return mixed
     * @throws NotFoundHttpException
     */
    public function getWechat()
    {
        if ($this->_wechat === null) {
            throw new NotFoundHttpException('The "wechat" property must be set.');
        }
        return $this->_wechat;
    }

    /**
     * 根据ID查找公众号
     * @param $id
     * @return Object
     * @throws NotFoundHttpException
     */
    protected function findWechat($appid)
    {
        if(intval($appid) === 0){

            $model = WechatAccounts::find()->where('`key`=:key',[':key'=>$appid])->one();
        }else{
            $model = WechatAccounts::find()->where('`id`=:id',[':id'=>$appid])->one();
        }

        if ($model !== null) {
            return $model;
        } else {
            throw new yii\web\NotFoundHttpException('The requested page does not exist.');
        }

    }





    /**
     * 回复规则匹配
     * @return array|mixed
     */
    public function match()
    {
        if ($this->message['MsgType'] == 'event') { // 事件
            $method = 'matchEvent' . $this->message['Event'];
        } else {
            $method = 'match' . $this->message['MsgType'];
        }
        $matches = [];
        if (method_exists($this, $method)) {
            $matches = call_user_func([$this, $method]);
        }

//        return array_merge([
//            ['route' => '/wechat/fans/subscribe'] // 默认所有请求都做一次关注请求处理
//        ], $matches);

        return $matches;
    }

    /**
     * 文本消息关键字触发
     * @return array
     */
    protected function matchText()
    {
        return WechatReplyKeyword::find()
            ->keyword($this->message['Content'])
            ->wechatRule($this->getWechat()->id)
            ->limitTime(time())
            ->all();
    }

    /**
     * 图片消息触发
     * @return mixed
     */
    protected function matchImage()
    {
        return WechatReplyKeyword::find()
            ->andFilterWhere(['matchtype' => WechatReplyKeyword::TYPE_IMAGE])
            ->wechatRule($this->getWechat()->id)
            ->limitTime(time())
            ->all();
    }

    /**
     * 音频消息触发
     * @return mixed
     */
    protected function matchVoice()
    {
        return WechatReplyKeyword::find()
            ->andFilterWhere(['matchtype' => WechatReplyKeyword::TYPE_VOICE])
            ->wechatRule($this->getWechat()->id)
            ->limitTime(time())
            ->all();
    }

    /**
     * 视频, 短视频消息触发
     * @return mixed
     */
    protected function matchVideo()
    {
        return WechatReplyKeyword::find()
            ->andFilterWhere(['matchtype' => [WechatReplyKeyword::TYPE_VIDEO, WechatReplyKeyword::TYPE_SHORT_VIDEO]])
            ->wechatRule($this->getWechat()->id)
            ->limitTime(time())
            ->all();
    }

    /**
     * 位置消息触发
     * @return mixed
     */
    protected function matchLocation()
    {
        return WechatReplyKeyword::find()
            ->andFilterWhere(['matchtype' => [WechatReplyKeyword::TYPE_LOCATION]])
            ->wechatRule($this->getWechat()->id)
            ->limitTime(time())
            ->all();
    }

    /**
     * 链接消息触发
     * @return mixed
     */
    protected function matchLink()
    {
        return WechatReplyKeyword::find()
            ->andFilterWhere(['matchtype' => [WechatReplyKeyword::TYPE_LINK]])
            ->wechatRule($this->getWechat()->id)
            ->limitTime(time())
            ->all();
    }

    /**
     * 关注事件
     * @return array|void
     */
    protected function matchEventSubscribe()
    {

        // 扫码关注
        if (array_key_exists('Eventkey', $this->message) && strexists($this->message['Eventkey'], 'qrscene')) {
            $this->message['Eventkey'] = explode('_', $this->message['Eventkey'])[1]; // 取二维码的参数值
            return $this->matchEventScan();
        }else{
            return [['route' => '/wechat/fans/subscribe']];
        }

    }

    /**
     * 取消关注事件
     * @return array
     */
    protected function matchEventUnsubscribe()
    {
        // 取消关注默认处理
        return [['route' => '/wechat/fans/unsubscribe']];
    }

    /**
     * 用户已关注时的扫码事件触发
     * @return array
     */
    protected function matchEventScan()
    {
        if (array_key_exists('Eventkey', $this->message)) {
            $this->message['Content'] = $this->message['EventKey'];
            return $this->matchText();
        }
        return [];
    }

    /**
     * 上报地理位置事件触发
     * @return mixed
     */
    protected function matchEventLocation()
    {
        return $this->matchLocation(); // 直接匹配位置消息
    }

    /**
     * 点击菜单拉取消息时的事件触发
     * @return array
     */
    protected function matchEventClick()
    {
        // 触发作为关键字处理
        if (array_key_exists('EventKey', $this->message)) {
            $this->message['Content'] = $this->message['EventKey']; // EventKey作为关键字Content
            return $this->matchText();
        }
        return [];
    }

    /**
     * 点击菜单跳转链接时的事件触发
     * @return array
     */
    protected function matchEventView()
    {
        // 链接内容作为关键字
        if (array_key_exists('EventKey', $this->message)) {
            $this->message['Content'] = $this->message['EventKey']; // EventKey作为关键字Content
            return $this->matchText();
        }
        return [];
    }


}